Skip to content

✨ 대학 카탈로그 SSG 실패 시 CSR 폴백 추가 - #623

Merged
manNomi merged 1 commit into
mainfrom
feat/university-ssg-csr-fallback
Aug 3, 2026
Merged

✨ 대학 카탈로그 SSG 실패 시 CSR 폴백 추가#623
manNomi merged 1 commit into
mainfrom
feat/university-ssg-csr-fallback

Conversation

@manNomi

@manNomi manNomi commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

먼저, SSG는 실패하고 있지 않습니다

"중앙대가 SSG로 안 만들어진다"는 증상을 확인해봤는데, 빌드는 정상이고 중앙대 페이지도 생성됩니다. (#622 브랜치 기준)

홈 대학 생성된 HTML
인하대 1개 (목록만, 상세 0개)
경희대 171개 (목록 1 + 상세 170)
중앙대 187개 (목록 1 + 상세 186)

다만 인하대는 상세 페이지가 0개입니다. 공개 API가 homeUniversityId=1에 대해 대학을 0건 반환하기 때문입니다(경희대 170건, 중앙대 186건). 서버 데이터 쪽 확인이 필요해 보입니다 — 이 PR 범위 밖입니다.

이 PR이 하는 일

정적 생성에 실패하거나 서버에서 데이터를 못 가져왔을 때, 404·빈 화면으로 굳히지 않고 브라우저에서 같은 API를 다시 조회하도록 폴백을 추가합니다.

변경 내용

  • getAllUniversitiesSafe() 추가 — 실패 시 throw 대신 null 반환. 빈 배열이 아니라 null인 이유는 "0건인 정상 응답"과 "조회 실패"를 호출부가 반드시 구분하게 하기 위함입니다.
  • UniversityListCsrFallback / UniversityDetailCsrFallback 신규 — 기존 UniversityListContent / UniversityDetail을 그대로 재사용하고 데이터만 react-query로 다시 가져옵니다. QueryProvider와 useGetUniversityDetail 훅은 이미 있던 것을 씁니다.
  • [homeUniversity]/[id]dynamicParamstrue로 변경 — 정적 목록에서 빠진 경로가 404가 되지 않고 요청 시점에 렌더되도록. 그때도 실패하면 CSR 폴백이 받습니다.
  • generateStaticParams가 조회 실패한 홈 대학만 건너뛰고 빌드를 계속합니다.

동작 확인

API를 완전히 죽인 상태(NEXT_PUBLIC_API_SERVER_URL을 도달 불가 호스트로)로 빌드했습니다.

[university-web] 대학 목록 조회 실패 (status 500) - CSR 폴백으로 전환합니다.  (×4)
✓ Generating static pages using 10 workers (16/16)
  • 빌드 성공. 변경 전에는 assertUniversitySsgResponse가 throw해서 빌드가 깨졌습니다.
  • 생성된 kyunghee.html / inha.html파견학교 목록을 불러오는 중입니다 로딩 셸이 포함되어, 하이드레이션 후 클라이언트가 데이터를 채웁니다.
  • 정상 API로 빌드 시 기존과 동일하게 374개 페이지 생성(회귀 없음).

가드레일 문서 갱신

.claude/skills/university-web-rewrite-caution/SKILL.md는 지금까지 "SSG fetch 실패 시 빌드가 실패해야 한다" 를 유지 원칙으로 명시하고 있었습니다. 이 PR이 그 동작을 바꾸므로 문서도 함께 수정했습니다. 안 고치면 다음 작업자가 되돌립니다.

원칙의 본래 의도("빈 카탈로그를 조용히 정적으로 굳히지 않는다")는 유지했습니다 — 실패를 삼켜 빈 배열을 렌더하는 코드는 여전히 금지이고, 실패 시 반드시 (a) 빌드 로그에 남기고 (b) CSR 폴백을 렌더해야 한다고 명시했습니다. noConsole이 error인 앱이라 로그 한 줄에는 사유를 적은 biome-ignore를 달았습니다.

assertUniversitySsgResponse를 쓰는 기존 경로는 그대로 throw합니다. 폴백이 필요한 호출부만 *Safe 변형을 씁니다.

트레이드오프

정적 생성이 조용히 축소될 수 있다는 점은 실제 비용입니다. 예전엔 빌드 실패로 즉시 드러났지만 이제는 빌드가 통과합니다. 그래서 실패를 빌드 로그에 남기도록 했지만, CI에서 이 경고를 감지해 알림을 주는 장치는 없습니다. 배포 파이프라인에서 대학 목록 조회 실패 문자열을 감시하는 것을 권장합니다.

검증

  • pnpm --filter @solid-connect/university-web run lint:check — 321 files 통과
  • pnpm --filter @solid-connect/university-web run typecheck:ci — 통과
  • pnpm --filter @solid-connect/university-web run build — 정상 API / API 장애 양쪽 모두 성공

🤖 Generated with Claude Code

@manNomi
manNomi requested a review from wibaek as a code owner August 3, 2026 14:39
@vercel

vercel Bot commented Aug 3, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
solid-connect-university-web Ready Ready Preview Aug 3, 2026 2:41pm
solid-connect-web-admin Ready Ready Preview Aug 3, 2026 2:41pm
solid-connection-web Ready Ready Preview Aug 3, 2026 2:41pm

@coderabbitai

coderabbitai Bot commented Aug 3, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@manNomi, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 37 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 8267adeb-71cd-40e0-b2ce-7038bcccced8

📥 Commits

Reviewing files that changed from the base of the PR and between 67d3dc0 and bed525b.

📒 Files selected for processing (7)
  • .claude/skills/university-web-rewrite-caution/SKILL.md
  • apps/university-web/src/apis/universities/server/getSearchUniversitiesByText.ts
  • apps/university-web/src/apis/universities/server/index.ts
  • apps/university-web/src/app/university/[homeUniversity]/[id]/_ui/UniversityDetailCsrFallback.tsx
  • apps/university-web/src/app/university/[homeUniversity]/[id]/page.tsx
  • apps/university-web/src/app/university/[homeUniversity]/_ui/UniversityListCsrFallback.tsx
  • apps/university-web/src/app/university/[homeUniversity]/page.tsx

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: bed525b595

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

isError,
} = useQuery<SearchTextResponse, Error, ListUniversity[]>({
queryKey: [QueryKeys.universities.searchText, { homeUniversityId }],
queryFn: () => universitiesApi.getSearchText({ value: "", homeUniversityId }),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Keep the CSR fallback on the configured term

When NEXT_PUBLIC_UNIVERSITY_TERM_ID is configured, the server-side getAllUniversitiesSafe() automatically includes that term, but this fallback calls getSearchText without useDefaultTermId: true; getScopedTermId therefore omits termId. If the build-time request fails, the recovered page can display universities from every term instead of the catalog that would have been statically generated.

Useful? React with 👍 / 👎.

Comment on lines +16 to +17
// 정적 생성에 실패해 목록에 빠진 경로도 요청 시점에 렌더링한다(404 대신 CSR 폴백으로 이어짐).
export const dynamicParams = true;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Reject mismatched home-university detail URLs

With dynamicParams = true, a request such as /university/inha/<kyunghee-id> is no longer rejected by the generated-parameter whitelist. CollegeDetailPage fetches the detail using only the numeric ID and never verifies that it belongs to the selected home university, so the page renders valid content under the wrong navigation, canonical URL, and metadata. Validate the ID against the scoped university list before rendering, while retaining the fallback only when that validation request itself fails.

Useful? React with 👍 / 👎.

Comment on lines +45 to +46
6. **SSG 데이터 페칭 실패는 CSR 폴백으로 넘긴다. 단, 조용히 빈 화면을 만들지 않는다.**
- 카탈로그 목록/상세는 정적 생성에 실패해도 **빌드를 중단시키지 않고** 클라이언트에서 같은 API를 다시 조회한다.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Update the deployment verification contract

This runbook now requires SSG fetch failures to complete the build with a CSR fallback, but the referenced docs/university-multizone-deployment.md verification section still says such a fetch failure must fail the build. Anyone following the documented cold-build check will treat the newly intended result as a regression, so the deployment reference needs to be updated with this behavior change.

AGENTS.md reference: AGENTS.md:L94-L100

Useful? React with 👍 / 👎.

@manNomi
manNomi merged commit 17f4777 into main Aug 3, 2026
13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

university Changes in apps/university-web

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant